package org.taobao.ibatiside.ui.wizard;

import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.PageBook;
import org.taobao.ibatiside.model.mapperv2.ParameterMap;
import org.taobao.ibatiside.model.mapperv2.SqlMap;
import org.taobao.ibatiside.model.mapperv2.TypeAlias;
import org.taobao.ibatiside.ui.util.ClassField;
import org.taobao.ibatiside.ui.util.MiscHelper;
import org.taobao.ibatiside.ui.util.TypeWrapper;
import org.taobao.ibatiside.ui.util.WorkspaceUtil;

public class StatementParameterComposite extends PageComposite {
	private Button btnUseParameterClass;
	private Button btnUserParameterMap;
	private ComboViewer comboParameterClass;
	private Combo comboParameterMap;
	private Button btnCreateNewMap;
	private Text textShowParaClassFQN;
	private NewParameterMapComposite newParameterMapComposite;
	private PageBook parameterDetails;
	private Composite blankComposite;
	private ComboViewer comboParameterListViewer;
	private List<TypeWrapper> typeWrappers;
	private ShowParameterClassInfoComposite compClsInfo;
	private ShowParameterMapInfoComposite compMapInfo;

	// for design time
	public StatementParameterComposite(Composite parent, int style) {
		super(parent, style);
	}

	public StatementParameterComposite(Composite parent, int style,
			BatisCommonPage page) {
		super(parent, style, page);
	}

	private void initTypeWrappers() {
		typeWrappers = new ArrayList<TypeWrapper>();
		typeWrappers.add(MiscHelper.TYPEWRAPPER_INTERAL_CATEGORY);
		typeWrappers.addAll(Arrays.asList(MiscHelper.INTERAL_TYPE_WRAPPER));
		typeWrappers.add(MiscHelper.TYPEWRAPPER_SELECT_CATEGORY);
		typeWrappers.add(MiscHelper.TYPEWRAPPER_DO_CATEGORY);
		typeWrappers.add(MiscHelper.TYPEWRAPPER_ALIAS_CATEGORY);
	}

	@Override
	public void doNotifyChanged(Notification notification) {

	}

	@Override
	protected void doPropertyChange(PropertyChangeEvent evt) {
		String pn = evt.getPropertyName();
		if (BatisSettingModel.K_SQLMAP.equals(pn)) {
			SqlMap new_map = (SqlMap) evt.getNewValue();
			comboParameterListViewer.setInput(new_map.getParameterMap());
			MiscHelper.removeAndAddNewTypeAlias(typeWrappers, new_map.getTypeAlias());
			comboParameterClass.refresh();
		} else if (BatisSettingModel.K_BEAN_NEED_CREATE.equals(pn)) {

		} else if (BatisSettingModel.K_PARAMETER_CLASS.equals(pn)) {
			TypeWrapper wrapper = (TypeWrapper) evt.getNewValue();
			if (wrapper != null) {
				showClass(wrapper);
			}
		}else if (BatisSettingModel.K_PARAMETER_MAP.equals(pn)){
			ParameterMap new_map = (ParameterMap) evt.getNewValue();
			if (new_map != null){
				showMap(new_map);
			}
		}
	}

	private void showMap(ParameterMap new_map) {
		compMapInfo.setParameterMap(new_map);
		parameterDetails.showPage(compMapInfo);
	}

	private void showClass(TypeWrapper wrapper) {
		List<ClassField> fields = new ArrayList<ClassField>();
		String typeLiteral = wrapper.getTypeLiteral();
		int cat = wrapper.getCategory();
		if (cat == TypeWrapper.NEW_CREATE) {
			String cls_name = StringUtils
					.defaultString(WorkspaceUtil.getClassPathString(model
							.getConfigurationFile().getProject(), model
							.getBeanPath()));
			textShowParaClassFQN.setText(cls_name);
			compClsInfo.setClassFQN(cls_name);
			fields.addAll(MiscHelper.toBeClassField(model.getBeanFields()));
		} else if (cat == TypeWrapper.INTERAL) {
			ClassField uni_field = new ClassField(typeLiteral);
			uni_field.setType(typeLiteral);
			uni_field.setGetExisted(true);
			uni_field.setSetExisted(false);
			fields.add(uni_field);
			compClsInfo.setClassFQN(typeLiteral);
		} else if (cat == TypeWrapper.PUBLIC) {
			textShowParaClassFQN.setText(typeLiteral);
			try {
				IType public_type = model.getCurrentProject().findType(
						typeLiteral);
				if (public_type != null) {
					compClsInfo.setClassFQN(typeLiteral);
					textShowParaClassFQN.setText(typeLiteral);
					fields.addAll(MiscHelper.loadReadableFields(public_type));
				}
			} catch (JavaModelException e) {
				e.printStackTrace();
				setErrorMessage(e.getLocalizedMessage());
			}
		} else if (cat == TypeWrapper.TYPE_ALIAS) {
			TypeAlias alias = MiscHelper.getAliasByLiteral(model.getSqlmap(),
					typeLiteral);
			try {
				IType fqn_type = model.getCurrentProject().findType(
						alias.getType());
				if (fqn_type == null) {
					setErrorMessage("Can't load alias '" + typeLiteral);
				} else {
					String fqn_name = fqn_type.getFullyQualifiedName();
					textShowParaClassFQN.setText(fqn_name);
					compClsInfo.setClassFQN(fqn_name);
					fields.addAll(MiscHelper.loadJavaBeanFields(fqn_type));
				}
			} catch (JavaModelException e) {
				e.printStackTrace();
				setErrorMessage(e.getLocalizedMessage());
			}
		}
		model.setActiveClassFields(fields);
		compClsInfo.setFields(fields);
		parameterDetails.showPage(compClsInfo);
	}
	@Override
	protected void createContent() {
		initTypeWrappers();
		setLayout(new GridLayout(1, false));
		Group group = new Group(this, SWT.NONE);
		group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1,
				1));
		group.setText("Parameter Input");
		group.setBounds(0, 0, 70, 84);
		group.setLayout(new FormLayout());

		btnUseParameterClass = new Button(group, SWT.RADIO);
		btnUseParameterClass.setText("Use Parameter Class");
		FormData fd_btnUseParameterClass = new FormData();
		fd_btnUseParameterClass.top = new FormAttachment(0, 4);
		fd_btnUseParameterClass.right = new FormAttachment(30);
		fd_btnUseParameterClass.left = new FormAttachment(0, 7);
		btnUseParameterClass.setLayoutData(fd_btnUseParameterClass);
		btnUseParameterClass.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				model.setParameterRequired(true);
				model.setParameterUseClass(true);
			}
		});
		btnUserParameterMap = new Button(group, SWT.RADIO);
		btnUserParameterMap.setText("Use Parameter Map");
		FormData fd_btnUserParameterMap = new FormData();
		fd_btnUserParameterMap.top = new FormAttachment(0, 35);
		fd_btnUserParameterMap.right = new FormAttachment(30);
		fd_btnUserParameterMap.left = new FormAttachment(0, 7);
		btnUserParameterMap.setLayoutData(fd_btnUserParameterMap);
		btnUserParameterMap.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				model.setParameterRequired(true);
				model.setParameterUseClass(false);
			}
		});
		comboParameterClass = new ComboViewer(group, SWT.NONE);
		FormData fd_comboParameterClass = new FormData();
		fd_comboParameterClass.right = new FormAttachment(50);
		fd_comboParameterClass.left = new FormAttachment(btnUseParameterClass,
				6);
		comboParameterClass.setContentProvider(new ArrayContentProvider());
		comboParameterClass.setLabelProvider(new TypeWrapperLabelProvider());
		comboParameterClass.getControl().setLayoutData(fd_comboParameterClass);
		comboParameterClass
				.addSelectionChangedListener(new ISelectionChangedListener() {
					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						if (!event.getSelection().isEmpty()) {
							TypeWrapper selected_wrapper = (TypeWrapper) ((IStructuredSelection) event
									.getSelection()).getFirstElement();
							TypeWrapper detailWrapper = MiscHelper.getDetailWrapper(getShell(), selected_wrapper);
							if (detailWrapper != null) model.setParameterClass(detailWrapper);
						}
					}
				});
		comboParameterListViewer = new ComboViewer(group, SWT.READ_ONLY);
		comboParameterListViewer.setContentProvider(new ArrayContentProvider());
		comboParameterListViewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				return ((ParameterMap) element).getId();
			}
		});
		comboParameterMap = comboParameterListViewer.getCombo();
		FormData fd_comboParameterMap = new FormData();
		fd_comboParameterMap.right = new FormAttachment(60);
		fd_comboParameterMap.top = new FormAttachment(0, 30);
		fd_comboParameterMap.left = new FormAttachment(btnUserParameterMap, 6);
		comboParameterMap.setLayoutData(fd_comboParameterMap);
		comboParameterListViewer
				.addSelectionChangedListener(new ISelectionChangedListener() {
					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						if (!event.getSelection().isEmpty()) {
							model.setParameterMap((ParameterMap) ((IStructuredSelection) event
									.getSelection()).getFirstElement());
						}
					}
				});
		btnCreateNewMap = new Button(group, SWT.NONE);
		btnCreateNewMap.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				newParameterMapComposite.renew();
				parameterDetails.showPage(newParameterMapComposite);
				btnCreateNewMap.setEnabled(false);
			}
		});
		btnCreateNewMap.setText("Create New Map");
		FormData fd_btnCreateNewMap = new FormData();
		fd_btnCreateNewMap.top = new FormAttachment(btnUserParameterMap, -5,
				SWT.TOP);
		fd_btnCreateNewMap.left = new FormAttachment(comboParameterMap, 6);
		btnCreateNewMap.setLayoutData(fd_btnCreateNewMap);

		textShowParaClassFQN = new Text(group, SWT.BORDER | SWT.READ_ONLY);
		FormData fd_textShowParaClassFQN = new FormData();
		fd_textShowParaClassFQN.right = new FormAttachment(90);
		fd_textShowParaClassFQN.top = new FormAttachment(
				comboParameterClass.getControl(), 0, SWT.TOP);
		fd_textShowParaClassFQN.left = new FormAttachment(
				comboParameterClass.getControl(), 6);
		textShowParaClassFQN.setLayoutData(fd_textShowParaClassFQN);

		parameterDetails = new PageBook(this, SWT.NONE);
		parameterDetails.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1));
		blankComposite = new Composite(parameterDetails, SWT.NONE);

		newParameterMapComposite = new NewParameterMapComposite(
				parameterDetails, SWT.NONE, this.hostPage) {

			@Override
			protected void okPressed() {
				ParameterMap new_created_map = newParameterMapComposite.newParameterMap;
				model.getSqlmap().getParameterMap().add(new_created_map);
				comboParameterListViewer.refresh();
				comboParameterListViewer.setSelection(new StructuredSelection(
						new_created_map));
				btnCreateNewMap.setEnabled(true);
			}

			@Override
			protected void cancelPressed() {
				parameterDetails.showPage(blankComposite);
				btnCreateNewMap.setEnabled(true);
			}

		};
		
		compMapInfo = new ShowParameterMapInfoComposite(parameterDetails, SWT.NONE);
		compClsInfo = new ShowParameterClassInfoComposite(parameterDetails,SWT.NONE);
		parameterDetails.showPage(blankComposite);
		comboParameterClass.setInput(typeWrappers);
	}

	@Override
	protected void doBinding(EMFDataBindingContext bindingContext) {
		super.doBinding(bindingContext);
		ISWTObservableValue ob_control_check_para_class = SWTObservables.observeSelection(btnUseParameterClass);
		ISWTObservableValue ob_control_para_class_combo = SWTObservables.observeEnabled(comboParameterClass.getControl());
		bindingContext.bindValue(ob_control_para_class_combo, ob_control_check_para_class);
		
		ISWTObservableValue ob_control_para_class_show = SWTObservables.observeEnabled(textShowParaClassFQN);
		bindingContext.bindValue(ob_control_para_class_show, ob_control_check_para_class);
		
		ISWTObservableValue ob_control_check_param_map = SWTObservables.observeSelection(btnUserParameterMap);
		ISWTObservableValue ob_control_para_map_combo = SWTObservables.observeEnabled(comboParameterMap);
		bindingContext.bindValue(ob_control_para_map_combo, ob_control_check_param_map);
		
		ISWTObservableValue ob_control_create_parammap = SWTObservables.observeEnabled(btnCreateNewMap);
		bindingContext.bindValue(ob_control_create_parammap, ob_control_check_param_map);
	}
}
